import math
import cv2
import  numpy as np
#mp相关参数
import mediapipe as mp
mp_drawing=mp.solutions.drawing_utils
mp_drawing_styles=mp.solutions.drawing_styles
mp_hands=mp.solutions.hands
#model_complexity 作用：控制手部检测模型的复杂度等级 取值范围：0（轻量级）、1（平衡）、2（高精度）。默认值为 1。
#min_detection_confidence 作用：手部检测的置信度阈值。 取值范围：[0.0, 1.0]，默认值为 0.5。
#min_tracking_confidence 作用：手部跟踪的置信度阈值。 取值范围：[0.0, 1.0]，默认值为 0.5
hands=mp_hands.Hands(
    model_complexity=1,
    min_detection_confidence=0.5,
    min_tracking_confidence=0.5
)
#获取摄像头视频流
cap=cv2.VideoCapture(0)
#获取画面宽度和高度（因为mediapipe框架中对长宽进行了计算）
width=int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height=int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
#方块、坐标相关参数
square_x=100
square_y=100
square_width=100
square_height=100
L1=0
L2=0
on_square=False
square_color=(255,0,255)
while True:
    #获取每一帧
    ret,frame=cap.read()
    #对图像进行处理
    frame=cv2.flip(frame,1)
    #mediapipe处理
    frame.flags.writeable=False
    frame=cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
    results=hands.process(frame)
    frame.flags.writeable=True
    frame=cv2.cvtColor(frame,cv2.COLOR_RGB2BGR)
    if results.multi_hand_landmarks:
        for hand_landmarks in results.multi_hand_landmarks:
            mp_drawing.draw_landmarks(
                frame,
                hand_landmarks,
                mp_hands.HAND_CONNECTIONS,
                mp_drawing_styles.get_default_hand_landmarks_style(),
                mp_drawing_styles.get_default_hand_connections_style()
            )
        x_list=[]
        y_list=[]
        for landmark in hand_landmarks.landmark:
            x_list.append(landmark.x)
            y_list.append(landmark.y)
        #获取食指坐标
        index_finger_x=int(x_list[8]*width)
        index_finger_y=int(y_list[8]*height)
        #获取中指坐标
        middle_finger_x=int(x_list[12]*width)
        middle_finger_y=int(y_list[12]*height)
        #计算食指与中指指尖距离（两点之间坐标公式）
        finger_len=math.hypot((index_finger_x-middle_finger_x),(index_finger_y-middle_finger_y))
        #画一个圆来验证是否可以显示在屏幕上
        #cv2.circle(frame,(index_finger_x,index_finger_y),20,(255,0,255),-1)
        #如果距离小于30才开始激活
        if finger_len<30:
            #判断食指指尖在不在方块上
            if (index_finger_x > square_x and index_finger_x<(square_x+square_width)
              and index_finger_y>square_y and index_finger_y<(square_y+square_width)):
                if on_square==False:
                    #print("在方块上")
                    L1=abs(index_finger_x-square_x)
                    L2=abs(index_finger_y-square_y)
                    on_square=True
                else:
                    pass
        else:
            on_square=False
            square_color=(255,0,255)
        if on_square:
            square_x=index_finger_x-L1
            square_y=index_finger_y-L2
            square_color=(255,0,0)
    #注意颜色是BGR的顺序，方块参数是对角线上的两点坐标,-1表示实心
    #cv2.rectangle(frame,(square_x,square_y),(square_x+square_width,square_height+square_y),(255,0,0),-1)
    #画一个半透明的方块
    overplay=frame.copy()
    cv2.rectangle(frame,(square_x,square_y),(square_x+
    square_width,square_height+square_y),square_color,-1)
    frame=cv2.addWeighted(overplay,0.5,frame,0.5,0)
    #使鼠标可以调整窗口的大小
    #cv2.namedWindow('window', cv2.WINDOW_NORMAL)
    cv2.imshow('window', frame)
    #当按esc键时退出窗口
    if cv2.waitKey(10) & 0xFF ==27:
        break
#释放并关闭 窗口
cap.release()
cv2.destroyWindow('window')